﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Domain.Model.Repositories;
using Domain.Model.Comparendos;
using Domain.Model.Infracciones;
using Domain.Model.Infractores;
using Domain.Model.Agentes;
using Domain.Model.SecretariasDeTransito;
using Domain.Model.Vehiculos;
using Domain.Model.Base;
using Infrastructure.Base.Persistence;
using Domain.Model.Direcciones;

namespace Infrastructure.Base.InDatabase
{

    public class BComparendoRepository : ComparendoRepository
    {
        private List<Comparendo> lista;

        public BComparendoRepository()
        {
            this.lista = new List<Comparendo>();

        }

        #region Métodos Heredados Generales

        public override void Insert(Comparendo entity)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblComparendo obj = new TblComparendo();

            //Identidad
            obj.id = entity.Identity.Value.ToString();

            //Llaves Foráneas
            obj.pk_agente = this.PKAgenteFromId(entity.AgenteId);
            obj.pk_infractor = this.PKInfractorFromId(entity.InfractorId);
            obj.pk_vehiculo = this.PKVehiculoFromId(entity.VehiculoId);
            obj.pk_infraccion = this.PKInfraccionFromId(entity.InfraccionId);
            obj.pk_secretaria = this.PKSecretariaDeTransitoFromId(entity.SecretariaTransitoId);

            //Campos Propios
            obj.numero = entity.Numero.ToString();
            obj.fecha = entity.Fecha;
            obj.tipoInfractor = entity.TipoInfractor;
            obj.estado = entity.Estado;
            obj.observacion = entity.Observacion;

            //Objetos de Valor
            obj.domicilio = entity.Direccion.Domicilio;
            obj.municipio = entity.Direccion.Municipio;
            obj.localidad = entity.Direccion.Localidad;
            obj.codigoPostal = entity.Direccion.CodigoPostal;

            contexto.AddToTblComparendo(obj);
            contexto.SaveChanges();
            contexto.Dispose();
        }

        public override Comparendo FromId(ObjectIdentity id)
        {
            String idString = id.Value.ToString();
            ContextoInfraccion contexto = new ContextoInfraccion();
            
            TblComparendo item = contexto.TblComparendo.Where(I => I.id == idString).FirstOrDefault();
            contexto.Dispose();

            if (item != null)
            {
                Comparendo oComparendo = new Comparendo(new ComparendoId(item.id), item.numero, item.fecha, item.tipoInfractor, item.estado, item.observacion,
                    this.SecretariaDeTransitoIdFromPK((int)item.pk_secretaria),
                    this.VehiculoIdFromPK((int)item.pk_vehiculo),
                    this.InfraccionIdFromPK((int)item.pk_infraccion),
                    this.AgenteIdFromPK((int)item.pk_agente),
                    this.InfractorIdFromPK((int)item.pk_infractor),
                    new Direccion(item.domicilio, item.municipio, item.localidad, item.codigoPostal));

                //Asignar la llave primaria de la BD
                oComparendo.PK = item.pk_comparendo;

                return oComparendo;
            }

            return null;
        }

        public override ObjectIdentity NextIdentity()
        {
            return new ComparendoId(Guid.NewGuid().ToString().ToUpper());
        }

        public override void Update(Comparendo entity)
        {
            String idString = entity.Identity.Value.ToString();
            ContextoInfraccion contexto = new ContextoInfraccion();
            
            TblComparendo obj = contexto.TblComparendo.Where(I => I.id == idString).FirstOrDefault();

            //Identidad
            obj.id = entity.Identity.Value.ToString();

            //Llaves Foráneas
            obj.pk_agente = this.PKAgenteFromId(entity.AgenteId);
            obj.pk_infractor = this.PKInfractorFromId(entity.InfractorId);
            obj.pk_vehiculo = this.PKVehiculoFromId(entity.VehiculoId);
            obj.pk_infraccion = this.PKInfraccionFromId(entity.InfraccionId);
            obj.pk_secretaria = this.PKSecretariaDeTransitoFromId(entity.SecretariaTransitoId);

            //Campos Propios
            obj.numero = entity.Numero.ToString();
            obj.fecha = entity.Fecha;
            obj.tipoInfractor = entity.TipoInfractor;
            obj.estado = entity.Estado;
            obj.observacion = entity.Observacion;

            //Objetos de Valor
            obj.domicilio = entity.Direccion.Domicilio;
            obj.municipio = entity.Direccion.Municipio;
            obj.localidad = entity.Direccion.Localidad;
            obj.codigoPostal = entity.Direccion.CodigoPostal;

            contexto.SaveChanges();
            contexto.Dispose();
        }

        public override void Remove(ObjectIdentity id)
        {
            String idString = id.Value.ToString();
            ContextoInfraccion contexto = new ContextoInfraccion();

            TblComparendo obj = contexto.TblComparendo.Where(I => I.id == idString).FirstOrDefault();

            contexto.DeleteObject(obj);
            contexto.SaveChanges();
            contexto.Dispose();
        }

        public override List<Comparendo> All()
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            List<TblComparendo> listaBD = new List<TblComparendo>();

            listaBD = contexto.TblComparendo.OrderBy(I => I.numero).ToList();


            foreach (var item in listaBD)
            {
                Comparendo obj = new Comparendo(new ComparendoId(item.id), item.numero, item.fecha, item.tipoInfractor, item.estado, item.observacion,
                    this.SecretariaDeTransitoIdFromPK((int)item.pk_secretaria),
                    this.VehiculoIdFromPK((int)item.pk_vehiculo),
                    this.InfraccionIdFromPK((int)item.pk_infraccion),
                    this.AgenteIdFromPK((int)item.pk_agente),
                    this.InfractorIdFromPK((int)item.pk_infractor),
                    new Direccion(item.domicilio, item.municipio, item.localidad, item.codigoPostal));
                lista.Add(obj);
            }

            contexto.Dispose();
            return lista;
        }

        public override int Count()
        {
            return All().Count;
        }

        #endregion

        #region Métodos Nuevos

        public override List<Comparendo> FromIdInfractor(InfractorId idInfractor)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();

            List<TblComparendo> listaBD = new List<TblComparendo>();

            int pkInfractor = this.PKInfractorFromId(idInfractor);

            listaBD = contexto.TblComparendo.Where(I => I.pk_infractor == pkInfractor).ToList();
            foreach (var item in listaBD)
            {
                Comparendo obj = new Comparendo(new ComparendoId(item.id), item.numero, item.fecha, item.tipoInfractor, item.estado, item.observacion,
                    this.SecretariaDeTransitoIdFromPK((int)item.pk_secretaria),
                    this.VehiculoIdFromPK((int)item.pk_vehiculo),
                    this.InfraccionIdFromPK((int)item.pk_infraccion),
                    this.AgenteIdFromPK((int)item.pk_agente),
                    this.InfractorIdFromPK((int)item.pk_infractor),
                    new Direccion(item.domicilio, item.municipio, item.localidad, item.codigoPostal));
                lista.Add(obj);
            }

            contexto.Dispose();
            return lista;
        }

        #endregion


        #region Métodos de Base de Datos
        private SecretariaDeTransitoId SecretariaDeTransitoIdFromPK(int pkSecretaria)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblSecretariaDeTransito item = contexto.TblSecretariaDeTransito.Where(S => S.pk_secretaria == pkSecretaria).FirstOrDefault();
            contexto.Dispose();

            return new SecretariaDeTransitoId(item.id);
        }

        private VehiculoId VehiculoIdFromPK(int pkVehiculo)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblVehiculo item = contexto.TblVehiculo.Where(V => V.pk_vehiculo == pkVehiculo).FirstOrDefault();
            contexto.Dispose();

            return new VehiculoId(item.id);
        }

        private InfraccionId InfraccionIdFromPK(int pkInfraccion)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblInfraccion item = contexto.TblInfraccion.Where(V => V.pk_infraccion == pkInfraccion).FirstOrDefault();
            contexto.Dispose();

            return new InfraccionId(item.id);
        }

        private AgenteId AgenteIdFromPK(int pkAgente)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblAgente item = contexto.TblAgente.Where(V => V.pk_agente == pkAgente).FirstOrDefault();
            contexto.Dispose();

            return new AgenteId(item.id);
        }

        private InfractorId InfractorIdFromPK(int pkInfractor)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblInfractor item = contexto.TblInfractor.Where(V => V.pk_infractor == pkInfractor).FirstOrDefault();
            contexto.Dispose();

            return new InfractorId(item.id);
        }

        private int PKSecretariaDeTransitoFromId(SecretariaDeTransitoId identity)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblSecretariaDeTransito item = contexto.TblSecretariaDeTransito.Where(S => S.id == identity.Value).FirstOrDefault();
            contexto.Dispose();

            return item.pk_secretaria;
        }

        private int PKVehiculoFromId(VehiculoId identity)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblVehiculo item = contexto.TblVehiculo.Where(S => S.id == identity.Value).FirstOrDefault();
            contexto.Dispose();

            return item.pk_vehiculo;
        }

        private int PKInfraccionFromId(InfraccionId identity)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblInfraccion item = contexto.TblInfraccion.Where(S => S.id == identity.Value).FirstOrDefault();
            contexto.Dispose();

            return item.pk_infraccion;
        }

        private int PKAgenteFromId(AgenteId identity)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblAgente item = contexto.TblAgente.Where(S => S.id == identity.Value).FirstOrDefault();
            contexto.Dispose();

            return item.pk_agente;
        }

        private int PKInfractorFromId(InfractorId identity)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblInfractor item = contexto.TblInfractor.Where(S => S.id == identity.Value).FirstOrDefault();
            contexto.Dispose();

            return item.pk_infractor;
        }
        #endregion
    }
}
